home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume7 / remtape < prev    next >
Encoding:
Internet Message Format  |  1986-12-16  |  28.5 KB

  1. Subject:  v07i091:  Remote magtape library for 4.3BSD
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: Arnold D. Robbins <linus!gatech!emoryu1!arnold>
  6. Mod.sources: Volume 7, Issue 91
  7. Archive-name: remtape
  8.  
  9. #! /bin/sh
  10. # This is a shell archive, meaning:
  11. # 1. Remove everything above the #! /bin/sh line.
  12. # 2. Save the resulting text in a file.
  13. # 3. Execute the file with /bin/sh (not csh) to create the files:
  14. #    README
  15. #    Makefile
  16. #    rmt.h
  17. #    rmtlib.c
  18. #    rmtops.3
  19. #    dd.1.patch
  20. #    dd.c.patch
  21. #    tar.1.patch
  22. #    tar.c.patch
  23. export PATH; PATH=/bin:$PATH
  24. echo shar: extracting "'README'" '(592 characters)'
  25. if test -f 'README'
  26. then
  27.     echo shar: will not over-write existing file "'README'"
  28. else
  29. cat << \SHAR_EOF > 'README'
  30. README
  31.  
  32. This is the remote mag tape library for 4.3 BSD. It is almost unchanged
  33. from the 4.2 version. However, I am sending the whole thing, since the first
  34. one is in the archives as an initial submission plus a patch, and it is
  35. small enough to be reposted again from scratch.
  36.  
  37. Besides the remote mag tape library (-lrmt) itself, I am including patches
  38. to tar, dd, and their man pages. I have used RCS this time around, therefore
  39. "your line numbers may vary". Patch should be able to handle it, though.
  40.  
  41. Enjoy,
  42.  
  43. Arnold Robbins
  44. Emory University Computing Center
  45. { akgua, gatech }!emory!arnold
  46. SHAR_EOF
  47. fi # end of overwriting check
  48. echo shar: extracting "'Makefile'" '(421 characters)'
  49. if test -f 'Makefile'
  50. then
  51.     echo shar: will not over-write existing file "'Makefile'"
  52. else
  53. cat << \SHAR_EOF > 'Makefile'
  54. #
  55. # $Header: Makefile,v 1.1 86/10/09 16:42:13 root Locked $
  56. #
  57. # $Log:    Makefile,v $
  58. # Revision 1.1  86/10/09  16:42:13  root
  59. # Initial revision
  60. #
  61. # Makefile for rmtlib
  62.  
  63. CFLAGS= -O
  64. SRC= rmtlib.c
  65. DOC= rmtops.3
  66.  
  67. MANSEC=3
  68. DEST= /usr/lib
  69.  
  70. librmt.a: rmtlib.o
  71.     ar rv librmt.a rmtlib.o
  72.  
  73. install: librmt.a
  74.     cp librmt.a /usr/lib
  75.     ranlib /usr/lib/librmt.a
  76.     cp $(DOC) /usr/man/man$(MANSEC)/rmtops.$(MANSEC)
  77.  
  78. clean:
  79.     rm -f rmtlib.o
  80. SHAR_EOF
  81. fi # end of overwriting check
  82. echo shar: extracting "'rmt.h'" '(1056 characters)'
  83. if test -f 'rmt.h'
  84. then
  85.     echo shar: will not over-write existing file "'rmt.h'"
  86. else
  87. cat << \SHAR_EOF > 'rmt.h'
  88. /*
  89.  * $Header: rmt.h,v 1.1 86/10/09 16:17:20 root Locked $
  90.  *
  91.  * $Log:    rmt.h,v $
  92.  * Revision 1.1  86/10/09  16:17:20  root
  93.  * Initial revision
  94.  * 
  95.  */
  96.  
  97. /*
  98.  *    rmt.h
  99.  *
  100.  *    Added routines to replace open(), close(), lseek(), ioctl(), etc.
  101.  *    The preprocessor can be used to remap these the rmtopen(), etc
  102.  *    thus minimizing source changes.
  103.  *
  104.  *    This file must be included before <sys/stat.h>, since it redefines
  105.  *    stat to be rmtstat, so that struct stat xyzzy; declarations work
  106.  *    properly.
  107.  *
  108.  *    -- Fred Fish (w/some changes by Arnold Robbins)
  109.  */
  110.  
  111.  
  112. #ifndef access        /* avoid multiple redefinition */
  113. #ifndef lint        /* in this case what lint doesn't know won't hurt it */
  114. #define access rmtaccess
  115. #define close rmtclose
  116. #define creat rmtcreat
  117. #define dup rmtdup
  118. #define fcntl rmtfcntl
  119. #define fstat rmtfstat
  120. #define ioctl rmtioctl
  121. #define isatty rmtisatty
  122. #define lseek rmtlseek
  123. #define lstat rmtlstat
  124. #define open rmtopen
  125. #define read rmtread
  126. #define stat rmtstat
  127. #define write rmtwrite
  128.  
  129. extern long rmtlseek ();    /* all the rest are int's */
  130. #endif
  131. #endif
  132. SHAR_EOF
  133. fi # end of overwriting check
  134. echo shar: extracting "'rmtlib.c'" '(14258 characters)'
  135. if test -f 'rmtlib.c'
  136. then
  137.     echo shar: will not over-write existing file "'rmtlib.c'"
  138. else
  139. cat << \SHAR_EOF > 'rmtlib.c'
  140. #ifndef lint
  141. static char *RCSid = "$Header: rmtlib.c,v 1.2 86/10/09 16:38:53 root Locked $";
  142. #endif
  143.  
  144. /*
  145.  * $Log:    rmtlib.c,v $
  146.  * Revision 1.2  86/10/09  16:38:53  root
  147.  * Changed to reflect 4.3BSD rcp syntax. ADR.
  148.  * 
  149.  * Revision 1.1  86/10/09  16:17:35  root
  150.  * Initial revision
  151.  * 
  152.  */
  153.  
  154. /*
  155.  *    rmt --- remote tape emulator subroutines
  156.  *
  157.  *    Originally written by Jeff Lee, modified some by Arnold Robbins
  158.  *
  159.  *    WARNING:  The man page rmt(8) for /etc/rmt documents the remote mag
  160.  *    tape protocol which rdump and rrestore use.  Unfortunately, the man
  161.  *    page is *WRONG*.  The author of the routines I'm including originally
  162.  *    wrote his code just based on the man page, and it didn't work, so he
  163.  *    went to the rdump source to figure out why.  The only thing he had to
  164.  *    change was to check for the 'F' return code in addition to the 'E',
  165.  *    and to separate the various arguments with \n instead of a space.  I
  166.  *    personally don't think that this is much of a problem, but I wanted to
  167.  *    point it out.
  168.  *    -- Arnold Robbins
  169.  *
  170.  *    Redone as a library that can replace open, read, write, etc, by
  171.  *    Fred Fish, with some additional work by Arnold Robbins.
  172.  */
  173.  
  174. /*
  175.  *    MAXUNIT --- Maximum number of remote tape file units
  176.  *
  177.  *    READ --- Return the number of the read side file descriptor
  178.  *    WRITE --- Return the number of the write side file descriptor
  179.  */
  180.  
  181. #define RMTIOCTL    1
  182.  
  183. #include <stdio.h>
  184. #include <signal.h>
  185. #include <sys/types.h>
  186.  
  187. #ifdef RMTIOCTL
  188. #include <sys/ioctl.h>
  189. #include <sys/mtio.h>
  190. #endif
  191.  
  192. #include <errno.h>
  193. #include <setjmp.h>
  194. #include <sys/stat.h>
  195.  
  196. #define BUFMAGIC    64    /* a magic number for buffer sizes */
  197. #define MAXUNIT    4
  198.  
  199. #define READ(fd)    (Ctp[fd][0])
  200. #define WRITE(fd)    (Ptc[fd][1])
  201.  
  202. static int Ctp[MAXUNIT][2] = { -1, -1, -1, -1, -1, -1, -1, -1 };
  203. static int Ptc[MAXUNIT][2] = { -1, -1, -1, -1, -1, -1, -1, -1 };
  204.  
  205. static jmp_buf Jmpbuf;
  206. extern int errno;
  207.  
  208. /*
  209.  *    abort --- close off a remote tape connection
  210.  */
  211.  
  212. static void abort(fildes)
  213. int fildes;
  214. {
  215.     close(READ(fildes));
  216.     close(WRITE(fildes));
  217.     READ(fildes) = -1;
  218.     WRITE(fildes) = -1;
  219. }
  220.  
  221.  
  222.  
  223. /*
  224.  *    command --- attempt to perform a remote tape command
  225.  */
  226.  
  227. static int command(fildes, buf)
  228. int fildes;
  229. char *buf;
  230. {
  231.     register int blen;
  232.     int (*pstat)();
  233.  
  234. /*
  235.  *    save current pipe status and try to make the request
  236.  */
  237.  
  238.     blen = strlen(buf);
  239.     pstat = signal(SIGPIPE, SIG_IGN);
  240.     if (write(WRITE(fildes), buf, blen) == blen)
  241.     {
  242.         signal(SIGPIPE, pstat);
  243.         return(0);
  244.     }
  245.  
  246. /*
  247.  *    something went wrong. close down and go home
  248.  */
  249.  
  250.     signal(SIGPIPE, pstat);
  251.     abort(fildes);
  252.  
  253.     errno = EIO;
  254.     return(-1);
  255. }
  256.  
  257.  
  258.  
  259. /*
  260.  *    status --- retrieve the status from the pipe
  261.  */
  262.  
  263. static int status(fildes)
  264. int fildes;
  265. {
  266.     int i;
  267.     char c, *cp;
  268.     char buffer[BUFMAGIC];
  269.  
  270. /*
  271.  *    read the reply command line
  272.  */
  273.  
  274.     for (i = 0, cp = buffer; i < BUFMAGIC; i++, cp++)
  275.     {
  276.         if (read(READ(fildes), cp, 1) != 1)
  277.         {
  278.             abort(fildes);
  279.             errno = EIO;
  280.             return(-1);
  281.         }
  282.         if (*cp == '\n')
  283.         {
  284.             *cp = 0;
  285.             break;
  286.         }
  287.     }
  288.  
  289.     if (i == BUFMAGIC)
  290.     {
  291.         abort(fildes);
  292.         errno = EIO;
  293.         return(-1);
  294.     }
  295.  
  296. /*
  297.  *    check the return status
  298.  */
  299.  
  300.     for (cp = buffer; *cp; cp++)
  301.         if (*cp != ' ')
  302.             break;
  303.  
  304.     if (*cp == 'E' || *cp == 'F')
  305.     {
  306.         errno = atoi(cp + 1);
  307.         while (read(READ(fildes), &c, 1) == 1)
  308.             if (c == '\n')
  309.                 break;
  310.  
  311.         if (*cp == 'F')
  312.             abort(fildes);
  313.  
  314.         return(-1);
  315.     }
  316.  
  317. /*
  318.  *    check for mis-synced pipes
  319.  */
  320.  
  321.     if (*cp != 'A')
  322.     {
  323.         abort(fildes);
  324.         errno = EIO;
  325.         return(-1);
  326.     }
  327.  
  328.     return(atoi(cp + 1));
  329. }
  330.  
  331.  
  332.  
  333. /*
  334.  *    _rmt_open --- open a magtape device on system specified, as given user
  335.  *
  336.  *    file name has the form system[.user]:/dev/????
  337.  */
  338.  
  339. #define MAXHOSTLEN    257    /* BSD allows very long host names... */
  340.  
  341. static int _rmt_open (path, oflag, mode)
  342. char *path;
  343. int oflag;
  344. int mode;
  345. {
  346.     int i, rc;
  347.     char buffer[BUFMAGIC];
  348.     char system[MAXHOSTLEN];
  349.     char device[BUFMAGIC];
  350.     char login[BUFMAGIC];
  351.     char *sys, *dev, *user;
  352.  
  353.     sys = system;
  354.     dev = device;
  355.     user = login;
  356.  
  357. /*
  358.  *    first, find an open pair of file descriptors
  359.  */
  360.  
  361.     for (i = 0; i < MAXUNIT; i++)
  362.         if (READ(i) == -1 && WRITE(i) == -1)
  363.             break;
  364.  
  365.     if (i == MAXUNIT)
  366.     {
  367.         errno = EMFILE;
  368.         return(-1);
  369.     }
  370.  
  371. /*
  372.  *    pull apart system and device, and optional user
  373.  *    don't munge original string
  374.  *    handle both old host.person and new person@site notations
  375.  */
  376.     while (*path != '@' && *path != '.' && *path != ':') {
  377.         *sys++ = *path++;
  378.     }
  379.     *sys = '\0';
  380.     path++;
  381.  
  382.     if (*(path - 1) == '@')
  383.     {
  384.         (void) strcpy (user, sys);    /* saw user part of user@host */
  385.         sys = system;            /* start over */
  386.         while (*path != ':') {
  387.             *sys++ = *path++;
  388.         }
  389.         *sys = '\0';
  390.         path++;
  391.     }
  392.     else if (*(path - 1) == '.')
  393.     {
  394.         while (*path != ':') {
  395.             *user++ = *path++;
  396.         }
  397.         *user = '\0';
  398.         path++;
  399.     }
  400.     else
  401.         *user = '\0';
  402.  
  403.     while (*path) {
  404.         *dev++ = *path++;
  405.     }
  406.     *dev = '\0';
  407.  
  408. /*
  409.  *    setup the pipes for the 'rsh' command and fork
  410.  */
  411.  
  412.     if (pipe(Ptc[i]) == -1 || pipe(Ctp[i]) == -1)
  413.         return(-1);
  414.  
  415.     if ((rc = fork()) == -1)
  416.         return(-1);
  417.  
  418.     if (rc == 0)
  419.     {
  420.         close(0);
  421.         dup(Ptc[i][0]);
  422.         close(Ptc[i][0]); close(Ptc[i][1]);
  423.         close(1);
  424.         dup(Ctp[i][1]);
  425.         close(Ctp[i][0]); close(Ctp[i][1]);
  426.         (void) setuid (getuid ());
  427.         (void) setgid (getgid ());
  428.         if (*user)
  429.         {
  430.             execl("/usr/ucb/rsh", "rsh", system, "-l", login,
  431.                 "/etc/rmt", (char *) 0);
  432.             execl("/usr/bin/remsh", "remsh", system, "-l", login,
  433.                 "/etc/rmt", (char *) 0);
  434.         }
  435.         else
  436.         {
  437.             execl("/usr/ucb/rsh", "rsh", system,
  438.                 "/etc/rmt", (char *) 0);
  439.             execl("/usr/bin/remsh", "remsh", system,
  440.                 "/etc/rmt", (char *) 0);
  441.         }
  442.  
  443. /*
  444.  *    bad problems if we get here
  445.  */
  446.  
  447.         perror("exec");
  448.         exit(1);
  449.     }
  450.  
  451.     close(Ptc[i][0]); close(Ctp[i][1]);
  452.  
  453. /*
  454.  *    now attempt to open the tape device
  455.  */
  456.  
  457.     sprintf(buffer, "O%s\n%d\n", device, oflag);
  458.     if (command(i, buffer) == -1 || status(i) == -1)
  459.         return(-1);
  460.  
  461.     return(i);
  462. }
  463.  
  464.  
  465.  
  466. /*
  467.  *    _rmt_close --- close a remote magtape unit and shut down
  468.  */
  469.  
  470. static int _rmt_close(fildes)
  471. int fildes;
  472. {
  473.     int rc;
  474.  
  475.     if (command(fildes, "C\n") != -1)
  476.     {
  477.         rc = status(fildes);
  478.  
  479.         abort(fildes);
  480.         return(rc);
  481.     }
  482.  
  483.     return(-1);
  484. }
  485.  
  486.  
  487.  
  488. /*
  489.  *    _rmt_read --- read a buffer from a remote tape
  490.  */
  491.  
  492. static int _rmt_read(fildes, buf, nbyte)
  493. int fildes;
  494. char *buf;
  495. unsigned int nbyte;
  496. {
  497.     int rc, i;
  498.     char buffer[BUFMAGIC];
  499.  
  500.     sprintf(buffer, "R%d\n", nbyte);
  501.     if (command(fildes, buffer) == -1 || (rc = status(fildes)) == -1)
  502.         return(-1);
  503.  
  504.     for (i = 0; i < rc; i += nbyte, buf += nbyte)
  505.     {
  506.         nbyte = read(READ(fildes), buf, rc);
  507.         if (nbyte <= 0)
  508.         {
  509.             abort(fildes);
  510.             errno = EIO;
  511.             return(-1);
  512.         }
  513.     }
  514.  
  515.     return(rc);
  516. }
  517.  
  518.  
  519.  
  520. /*
  521.  *    _rmt_write --- write a buffer to the remote tape
  522.  */
  523.  
  524. static int _rmt_write(fildes, buf, nbyte)
  525. int fildes;
  526. char *buf;
  527. unsigned int nbyte;
  528. {
  529.     int rc;
  530.     char buffer[BUFMAGIC];
  531.     int (*pstat)();
  532.  
  533.     sprintf(buffer, "W%d\n", nbyte);
  534.     if (command(fildes, buffer) == -1)
  535.         return(-1);
  536.  
  537.     pstat = signal(SIGPIPE, SIG_IGN);
  538.     if (write(WRITE(fildes), buf, nbyte) == nbyte)
  539.     {
  540.         signal (SIGPIPE, pstat);
  541.         return(status(fildes));
  542.     }
  543.  
  544.     signal (SIGPIPE, pstat);
  545.     abort(fildes);
  546.     errno = EIO;
  547.     return(-1);
  548. }
  549.  
  550.  
  551.  
  552. /*
  553.  *    _rmt_lseek --- perform an imitation lseek operation remotely
  554.  */
  555.  
  556. static long _rmt_lseek(fildes, offset, whence)
  557. int fildes;
  558. long offset;
  559. int whence;
  560. {
  561.     char buffer[BUFMAGIC];
  562.  
  563.     sprintf(buffer, "L%d\n%d\n", offset, whence);
  564.     if (command(fildes, buffer) == -1)
  565.         return(-1);
  566.  
  567.     return(status(fildes));
  568. }
  569.  
  570.  
  571. /*
  572.  *    _rmt_ioctl --- perform raw tape operations remotely
  573.  */
  574.  
  575. #ifdef RMTIOCTL
  576. static _rmt_ioctl(fildes, op, arg)
  577. int fildes, op;
  578. char *arg;
  579. {
  580.     char c;
  581.     int rc, cnt;
  582.     char buffer[BUFMAGIC];
  583.  
  584. /*
  585.  *    MTIOCOP is the easy one. nothing is transfered in binary
  586.  */
  587.  
  588.     if (op == MTIOCTOP)
  589.     {
  590.         sprintf(buffer, "I%d\n%d\n", ((struct mtop *) arg)->mt_op,
  591.             ((struct mtop *) arg)->mt_count);
  592.         if (command(fildes, buffer) == -1)
  593.             return(-1);
  594.         return(status(fildes));
  595.     }
  596.  
  597. /*
  598.  *    we can only handle 2 ops, if not the other one, punt
  599.  */
  600.  
  601.     if (op != MTIOCGET)
  602.     {
  603.         errno = EINVAL;
  604.         return(-1);
  605.     }
  606.  
  607. /*
  608.  *    grab the status and read it directly into the structure
  609.  *    this assumes that the status buffer is (hopefully) not
  610.  *    padded and that 2 shorts fit in a long without any word
  611.  *    alignment problems, ie - the whole struct is contiguous
  612.  *    NOTE - this is probably NOT a good assumption.
  613.  */
  614.  
  615.     if (command(fildes, "S\n") == -1 || (rc = status(fildes)) == -1)
  616.         return(-1);
  617.  
  618.     for (; rc > 0; rc -= cnt, arg += cnt)
  619.     {
  620.         cnt = read(READ(fildes), arg, rc);
  621.         if (cnt <= 0)
  622.         {
  623.             abort(fildes);
  624.             errno = EIO;
  625.             return(-1);
  626.         }
  627.     }
  628.  
  629. /*
  630.  *    now we check for byte position. mt_type is a small integer field
  631.  *    (normally) so we will check its magnitude. if it is larger than
  632.  *    256, we will assume that the bytes are swapped and go through
  633.  *    and reverse all the bytes
  634.  */
  635.  
  636.     if (((struct mtget *) arg)->mt_type < 256)
  637.         return(0);
  638.  
  639.     for (cnt = 0; cnt < rc; cnt += 2)
  640.     {
  641.         c = arg[cnt];
  642.         arg[cnt] = arg[cnt+1];
  643.         arg[cnt+1] = c;
  644.     }
  645.  
  646.     return(0);
  647.   }
  648. #endif /* RMTIOCTL */
  649.  
  650. /*
  651.  *    Added routines to replace open(), close(), lseek(), ioctl(), etc.
  652.  *    The preprocessor can be used to remap these the rmtopen(), etc
  653.  *    thus minimizing source changes:
  654.  *
  655.  *        #ifdef <something>
  656.  *        #  define access rmtaccess
  657.  *        #  define close rmtclose
  658.  *        #  define creat rmtcreat
  659.  *        #  define dup rmtdup
  660.  *        #  define fcntl rmtfcntl
  661.  *        #  define fstat rmtfstat
  662.  *        #  define ioctl rmtioctl
  663.  *        #  define isatty rmtisatty
  664.  *        #  define lseek rmtlseek
  665.  *        #  define lstat rmtlstat
  666.  *        #  define open rmtopen
  667.  *        #  define read rmtread
  668.  *        #  define stat rmtstat
  669.  *        #  define write rmtwrite
  670.  *        #  define access rmtaccess
  671.  *        #  define close rmtclose
  672.  *        #  define creat rmtcreat
  673.  *        #  define dup rmtdup
  674.  *        #  define fcntl rmtfcntl
  675.  *        #  define fstat rmtfstat
  676.  *        #  define ioctl rmtioctl
  677.  *        #  define lseek rmtlseek
  678.  *        #  define open rmtopen
  679.  *        #  define read rmtread
  680.  *        #  define stat rmtstat
  681.  *        #  define write rmtwrite
  682.  *        #endif
  683.  *
  684.  *    -- Fred Fish
  685.  *
  686.  *    ADR --- I set up a <rmt.h> include file for this
  687.  *
  688.  */
  689.  
  690. /*
  691.  *    Note that local vs remote file descriptors are distinquished
  692.  *    by adding a bias to the remote descriptors.  This is a quick
  693.  *    and dirty trick that may not be portable to some systems.
  694.  */
  695.  
  696. #define REM_BIAS 128
  697.  
  698.  
  699. /*
  700.  *    Test pathname to see if it is local or remote.  A remote device
  701.  *    is any string that contains ":/dev/".  Returns 1 if remote,
  702.  *    0 otherwise.
  703.  */
  704.  
  705. static int remdev (path)
  706. register char *path;
  707. {
  708. #define strchr    index
  709.     extern char *strchr ();
  710.  
  711.     if ((path = strchr (path, ':')) != NULL)
  712.     {
  713.         if (strncmp (path + 1, "/dev/", 5) == 0)
  714.         {
  715.             return (1);
  716.         }
  717.     }
  718.     return (0);
  719. }
  720.  
  721.  
  722. /*
  723.  *    Open a local or remote file.  Looks just like open(2) to
  724.  *    caller.
  725.  */
  726.  
  727. int rmtopen (path, oflag, mode)
  728. char *path;
  729. int oflag;
  730. int mode;
  731. {
  732.     if (remdev (path))
  733.     {
  734.         return (_rmt_open (path, oflag, mode) + REM_BIAS);
  735.     }
  736.     else
  737.     {
  738.         return (open (path, oflag, mode));
  739.     }
  740. }
  741.  
  742. /*
  743.  *    Test pathname for specified access.  Looks just like access(2)
  744.  *    to caller.
  745.  */
  746.  
  747. int rmtaccess (path, amode)
  748. char *path;
  749. int amode;
  750. {
  751.     if (remdev (path))
  752.     {
  753.         return (0);        /* Let /etc/rmt find out */
  754.     }
  755.     else
  756.     {
  757.         return (access (path, amode));
  758.     }
  759. }
  760.  
  761.  
  762. /*
  763.  *    Read from stream.  Looks just like read(2) to caller.
  764.  */
  765.   
  766. int rmtread (fildes, buf, nbyte)
  767. int fildes;
  768. char *buf;
  769. unsigned int nbyte;
  770. {
  771.     if (isrmt (fildes))
  772.     {
  773.         return (_rmt_read (fildes - REM_BIAS, buf, nbyte));
  774.     }
  775.     else
  776.     {
  777.         return (read (fildes, buf, nbyte));
  778.     }
  779. }
  780.  
  781.  
  782. /*
  783.  *    Write to stream.  Looks just like write(2) to caller.
  784.  */
  785.  
  786. int rmtwrite (fildes, buf, nbyte)
  787. int fildes;
  788. char *buf;
  789. unsigned int nbyte;
  790. {
  791.     if (isrmt (fildes))
  792.     {
  793.         return (_rmt_write (fildes - REM_BIAS, buf, nbyte));
  794.     }
  795.     else
  796.     {
  797.         return (write (fildes, buf, nbyte));
  798.     }
  799. }
  800.  
  801. /*
  802.  *    Perform lseek on file.  Looks just like lseek(2) to caller.
  803.  */
  804.  
  805. long rmtlseek (fildes, offset, whence)
  806. int fildes;
  807. long offset;
  808. int whence;
  809. {
  810.     if (isrmt (fildes))
  811.     {
  812.         return (_rmt_lseek (fildes - REM_BIAS, offset, whence));
  813.     }
  814.     else
  815.     {
  816.         return (lseek (fildes, offset, whence));
  817.     }
  818. }
  819.  
  820.  
  821. /*
  822.  *    Close a file.  Looks just like close(2) to caller.
  823.  */
  824.  
  825. int rmtclose (fildes)
  826. int fildes;
  827. {
  828.     if (isrmt (fildes))
  829.     {
  830.         return (_rmt_close (fildes - REM_BIAS));
  831.     }
  832.     else
  833.     {
  834.         return (close (fildes));
  835.     }
  836. }
  837.  
  838. /*
  839.  *    Do ioctl on file.  Looks just like ioctl(2) to caller.
  840.  */
  841.  
  842. int rmtioctl (fildes, request, arg)
  843. int fildes, request, arg;
  844. {
  845.     if (isrmt (fildes))
  846.     {
  847. #ifdef RMTIOCTL
  848.         return (_rmt_ioctl (fildes, request, arg));
  849. #else
  850.         errno = EOPNOTSUPP;
  851.         return (-1);        /* For now  (fnf) */
  852. #endif
  853.     }
  854.     else
  855.     {
  856.         return (ioctl (fildes, request, arg));
  857.     }
  858. }
  859.  
  860.  
  861. /*
  862.  *    Duplicate an open file descriptor.  Looks just like dup(2)
  863.  *    to caller.
  864.  */
  865.  
  866. int rmtdup (fildes)
  867. int fildes;
  868. {
  869.     if (isrmt (fildes))
  870.     {
  871.         errno = EOPNOTSUPP;
  872.         return (-1);        /* For now (fnf) */
  873.     }
  874.     else
  875.     {
  876.         return (dup (fildes));
  877.     }
  878. }
  879.  
  880. /*
  881.  *    Get file status.  Looks just like fstat(2) to caller.
  882.  */
  883.  
  884. int rmtfstat (fildes, buf)
  885. int fildes;
  886. struct stat *buf;
  887. {
  888.     if (isrmt (fildes))
  889.     {
  890.         errno = EOPNOTSUPP;
  891.         return (-1);        /* For now (fnf) */
  892.     }
  893.     else
  894.     {
  895.         return (fstat (fildes, buf));
  896.     }
  897. }
  898.  
  899.  
  900. /*
  901.  *    Get file status.  Looks just like stat(2) to caller.
  902.  */
  903.  
  904. int rmtstat (path, buf)
  905. char *path;
  906. struct stat *buf;
  907. {
  908.     if (remdev (path))
  909.     {
  910.         errno = EOPNOTSUPP;
  911.         return (-1);        /* For now (fnf) */
  912.     }
  913.     else
  914.     {
  915.         return (stat (path, buf));
  916.     }
  917. }
  918.  
  919.  
  920.  
  921. /*
  922.  *    Create a file from scratch.  Looks just like creat(2) to the caller.
  923.  */
  924.  
  925. #include <sys/file.h>        /* BSD DEPENDANT!!! */
  926. /* #include <fcntl.h>        /* use this one for S5 with remote stuff */
  927.  
  928. int rmtcreat (path, mode)
  929. char *path;
  930. int mode;
  931. {
  932.     if (remdev (path))
  933.     {
  934.         return (rmtopen (path, 1 | O_CREAT, mode));
  935.     }
  936.     else
  937.     {
  938.         return (creat (path, mode));
  939.     }
  940. }
  941.  
  942. /*
  943.  *    Isrmt. Let a programmer know he has a remote device.
  944.  */
  945.  
  946. int isrmt (fd)
  947. int fd;
  948. {
  949.     return (fd >= REM_BIAS);
  950. }
  951.  
  952. /*
  953.  *    Rmtfcntl. Do a remote fcntl operation.
  954.  */
  955.  
  956. int rmtfcntl (fd, cmd, arg)
  957. int fd, cmd, arg;
  958. {
  959.     if (isrmt (fd))
  960.     {
  961.         errno = EOPNOTSUPP;
  962.         return (-1);
  963.     }
  964.     else
  965.     {
  966.         return (fcntl (fd, cmd, arg));
  967.     }
  968. }
  969.  
  970. /*
  971.  *    Rmtisatty.  Do the isatty function.
  972.  */
  973.  
  974. int rmtisatty (fd)
  975. int fd;
  976. {
  977.     if (isrmt (fd))
  978.         return (0);
  979.     else
  980.         return (isatty (fd));
  981. }
  982.  
  983.  
  984. /*
  985.  *    Get file status, even if symlink.  Looks just like lstat(2) to caller.
  986.  */
  987.  
  988. int rmtlstat (path, buf)
  989. char *path;
  990. struct stat *buf;
  991. {
  992.     if (remdev (path))
  993.     {
  994.         errno = EOPNOTSUPP;
  995.         return (-1);        /* For now (fnf) */
  996.     }
  997.     else
  998.     {
  999.         return (lstat (path, buf));
  1000.     }
  1001. }
  1002. SHAR_EOF
  1003. fi # end of overwriting check
  1004. echo shar: extracting "'rmtops.3'" '(4477 characters)'
  1005. if test -f 'rmtops.3'
  1006. then
  1007.     echo shar: will not over-write existing file "'rmtops.3'"
  1008. else
  1009. cat << \SHAR_EOF > 'rmtops.3'
  1010. ...
  1011. ... $Header: rmtops.3,v 1.2 86/10/09 16:38:02 root Locked $
  1012. ... 
  1013. ... $Log:    rmtops.3,v $
  1014. ... Revision 1.2  86/10/09  16:38:02  root
  1015. ... Changed to reflect 4.3BSD rcp syntax and better rmt(8) capabilities. ADR.
  1016. ... 
  1017. ... Revision 1.1  86/10/09  16:18:47  root
  1018. ... Initial revision
  1019. ... 
  1020. ...
  1021. .TH RMTOPS 3 local
  1022. .SH NAME
  1023. rmtops \- access tape drives on remote machines
  1024. .SH SYNOPSIS
  1025. .nf
  1026. #include <rmt.h>
  1027. #include <sys/stat.h>    /* MUST come after <rmt.h> */
  1028.  
  1029. int isrmt (fd)
  1030. int fd;
  1031.  
  1032. int rmtaccess (file, mode)
  1033. char *file;
  1034. int mode;
  1035.  
  1036. int rmtclose (fd)
  1037. int fd;
  1038.  
  1039. int rmtcreat (file, mode)
  1040. char *file;
  1041. int mode;
  1042.  
  1043. int rmtdup (fd)
  1044. int fd;
  1045.  
  1046. int rmtfcntl (fd, cmd, arg)
  1047. int fd, cmd, arg;
  1048.  
  1049. int rmtfstat (fd, buf)
  1050. int fd;
  1051. struct stat *buf;
  1052.  
  1053. int rmtioctl (fd, request, argp)
  1054. int fd, request;
  1055. char *argp;
  1056.  
  1057. int rmtisatty (fd)
  1058. int fd;
  1059.  
  1060. long rmtlseek (fd, offset, whence)
  1061. int fd, whence;
  1062. long offset;
  1063.  
  1064. int rmtlstat (file, buf)
  1065. char *file;
  1066. struct stat *buf;
  1067.  
  1068. int rmtopen (file, flags [, mode])
  1069. char *file;
  1070. int flags, mode;
  1071.  
  1072. int rmtread (fd, buf, nbytes)
  1073. int fd, nbytes;
  1074. char *buf;
  1075.  
  1076. int rmtstat (file, buf)
  1077. char *file;
  1078. struct stat *buf;
  1079.  
  1080. int rmtwrite (fd, buf, nbytes)
  1081. int fd, nbytes;
  1082. char *buf;
  1083. .fi
  1084. .SH DESCRIPTION
  1085. .I Rmtops
  1086. provides a simple means of transparently accessing tape drives
  1087. on remote machines over the ethernet, via
  1088. .IR rsh (1)
  1089. and
  1090. .IR rmt (8).
  1091. These routines are used like their corresponding
  1092. system calls, but allow the user to open up a tape drive on a remote
  1093. system on which he or she has an account and the appropriate remote
  1094. permissions.
  1095. .PP
  1096. A remote tape drive file name has either of the forms
  1097. .sp
  1098. .RS
  1099. .RI [ user @] system :/dev/???
  1100. .RE
  1101. .sp
  1102. or
  1103. .sp
  1104. .RS
  1105. .IR system [. user ]:/dev/???
  1106. .RE
  1107. .sp
  1108. where
  1109. .I system
  1110. is the remote system,
  1111. .I /dev/???
  1112. is the particular drive on the remote system (raw, blocked, rewinding,
  1113. non-rewinding, etc.), and the optional
  1114. .I user
  1115. is the login name to be used on the remote system, if different from
  1116. the current user's login name.
  1117. The first form corresponds to the remote syntax used by
  1118. .IR rcp (1)
  1119. in 4.3BSD, the second form is for compatibility with
  1120. .IR rcp 's
  1121. syntax in 4.2BSD.
  1122. .PP
  1123. For transparency, the user should include the file
  1124. .IR <rmt.h> ,
  1125. which has the following defines in it:
  1126. .PP
  1127. .nf
  1128. #define access rmtaccess
  1129. #define close rmtclose
  1130. #define creat rmtcreat
  1131. #define dup rmtdup
  1132. #define fcntl rmtfcntl
  1133. #define fstat rmtfstat
  1134. #define ioctl rmtioctl
  1135. #define isatty rmtisatty
  1136. #define lseek rmtlseek
  1137. #define lstat rmtlstat
  1138. #define open rmtopen
  1139. #define read rmtread
  1140. #define stat rmtstat
  1141. #define write rmtwrite
  1142. .fi
  1143. .PP
  1144. This allows the programmer to use
  1145. .IR open ,
  1146. .IR close ,
  1147. .IR read ,
  1148. .IR write ,
  1149. etc. in their normal fashion, with the
  1150. .I rmtops
  1151. routines taking care of differentiating between local and remote files.
  1152. This file should be included
  1153. .I before
  1154. including the file
  1155. .IR <sys/stat.h> ,
  1156. since it redefines the identifier ``stat,'' which is used to declare
  1157. objects of type struct stat.
  1158. .PP
  1159. The routines differentiate between local and remote file descriptors by
  1160. adding a bias (currently 128) to the file descriptor of the pipe.
  1161. The programmer, if he must know if a file is remote, should use the
  1162. .I isrmt
  1163. function.
  1164. .SH FILES
  1165. .TP
  1166. .B /usr/lib/librmt.a
  1167. Contains the remote tape library.  To include the library with a program,
  1168. add the flag
  1169. .B \-lrmt
  1170. to the
  1171. .IR cc (1)
  1172. command line.
  1173. .SH SEE ALSO
  1174. .IR rcp (1),
  1175. .IR rsh (1),
  1176. .IR rmt (8),
  1177. and the appropriate system calls in section 2.
  1178. .SH DIAGNOSTICS
  1179. Several of these routines will return -1 and set
  1180. .I errno
  1181. to EOPNOTSUPP, if they are given a remote file name or a file descriptor
  1182. on an open remote file (e.g.,
  1183. .IR rmtdup ).
  1184. .SH BUGS
  1185. See diagnostics above.  It is to be hoped that true remote file systems
  1186. will eventually appear, and eliminate the need for these routines.
  1187. .PP
  1188. There is no way to use remote tape drives with the
  1189. .IR stdio (3)
  1190. package, short of recompiling it entirely to use these routines.
  1191. .PP
  1192. The
  1193. .IR rmt (8)
  1194. protocol is not very capable.  In particular, it relies on
  1195. TCP/IP sockets for error free transmission, and does no data validation
  1196. of its own.
  1197. .SH AUTHORS
  1198. Jeff Lee (gatech!jeff) wrote the original routines for accessing
  1199. tape drives via
  1200. .IR rmt (8).
  1201. .PP
  1202. Fred Fish (unisoft!fnf) redid them into a general purpose library.
  1203. .PP
  1204. Arnold Robbins
  1205. (formerly gatech!arnold, now emory!arnold)
  1206. added the ability to specify a user
  1207. name on the remote system, the
  1208. .I <rmt.h>
  1209. include file, this man page,
  1210. cleaned up the library a little,
  1211. and made the appropriate changes for 4.3BSD.
  1212. SHAR_EOF
  1213. fi # end of overwriting check
  1214. echo shar: extracting "'dd.1.patch'" '(1933 characters)'
  1215. if test -f 'dd.1.patch'
  1216. then
  1217.     echo shar: will not over-write existing file "'dd.1.patch'"
  1218. else
  1219. cat << \SHAR_EOF > 'dd.1.patch'
  1220. RCS file: RCS/dd.1,v
  1221. retrieving revision 1.1
  1222. diff -c -r1.1 dd.1
  1223. *** /tmp/,RCSt1012245    Thu Oct  9 16:50:49 1986
  1224. --- dd.1    Thu Oct  9 16:50:18 1986
  1225. ***************
  1226. *** 1,7 ****
  1227.   ...
  1228. ! ... $Header: dd.1,v 1.1 86/08/07 16:02:52 root Exp $
  1229.   ... 
  1230.   ... $Log:    dd.1,v $
  1231.   ... Revision 1.1  86/08/07  16:02:52  root
  1232.   ... Initial revision
  1233.   ... 
  1234. --- 1,13 ----
  1235.   ...
  1236. ! ... $Header: dd.1,v 1.3 86/10/09 16:50:02 root Locked $
  1237.   ... 
  1238.   ... $Log:    dd.1,v $
  1239. + ... Revision 1.3  86/10/09  16:50:02  root
  1240. + ... Changed to indicate use of 4.3 rcp syntax. ADR.
  1241. + ... 
  1242. + ... Revision 1.2  86/08/07  16:05:53  root
  1243. + ... Added doc of remote mag tape facility. ADR.
  1244. + ... 
  1245.   ... Revision 1.1  86/08/07  16:02:52  root
  1246.   ... Initial revision
  1247.   ... 
  1248. ***************
  1249. *** 38,48 ****
  1250.   .TP 
  1251.   if=
  1252.   input file name; standard input is default
  1253.   .br
  1254.   .ns
  1255.   .TP 
  1256.   of=
  1257. ! output file name; standard output is default
  1258.   .br
  1259.   .ns
  1260.   .TP 
  1261. --- 44,76 ----
  1262.   .TP 
  1263.   if=
  1264.   input file name; standard input is default
  1265. + If the input file name has either of the forms
  1266. + .RI [ user @] system :/dev/???,
  1267. + or
  1268. + .IR system [. user ]:/dev/???,
  1269. + then
  1270. + .I dd
  1271. + will attempt to use the tape drive /dev/??? on the remote system
  1272. + .IR system ,
  1273. + via
  1274. + .IR rsh (1),
  1275. + and
  1276. + .IR rmt (8).
  1277. + The optional
  1278. + .I user
  1279. + specifies the login name to use on the remote system.
  1280. + If it is not given, the current user's login name will be used.
  1281. + In all cases, the user must have the appropriate
  1282. + access permissions on the remote machine in order for this to work.
  1283. + (The first form is the 4.3BSD syntax for
  1284. + .IR rcp (1),
  1285. + the second is from 4.2BSD.)
  1286.   .br
  1287.   .ns
  1288.   .TP 
  1289.   of=
  1290. ! output file name; standard output is default,
  1291. ! remote file names may be used here as well.
  1292.   .br
  1293.   .ns
  1294.   .TP 
  1295. ***************
  1296. *** 233,235 ****
  1297. --- 261,265 ----
  1298.   Invalid combinations
  1299.   .I "silently ignore"
  1300.   all but the last mutually-exclusive keyword.
  1301. + .br
  1302. + Using a remote system's tape drive can be slow.
  1303. SHAR_EOF
  1304. fi # end of overwriting check
  1305. echo shar: extracting "'dd.c.patch'" '(871 characters)'
  1306. if test -f 'dd.c.patch'
  1307. then
  1308.     echo shar: will not over-write existing file "'dd.c.patch'"
  1309. else
  1310. cat << \SHAR_EOF > 'dd.c.patch'
  1311. RCS file: RCS/dd.c,v
  1312. retrieving revision 1.1
  1313. diff -c -r1.1 dd.c
  1314. *** /tmp/,RCSt1011946    Thu Oct  9 16:44:54 1986
  1315. --- dd.c    Thu Aug  7 15:55:33 1986
  1316. ***************
  1317. *** 1,9 ****
  1318.   #ifndef lint
  1319. ! static char *RCSid = "$Header: dd.c,v 1.1 86/08/07 15:52:39 root Exp $";
  1320.   #endif
  1321.   
  1322.   /*
  1323.    * $Log:    dd.c,v $
  1324.    * Revision 1.1  86/08/07  15:52:39  root
  1325.    * Initial revision
  1326.    * 
  1327. --- 1,12 ----
  1328.   #ifndef lint
  1329. ! static char *RCSid = "$Header: dd.c,v 1.2 86/08/07 15:55:17 root Locked $";
  1330.   #endif
  1331.   
  1332.   /*
  1333.    * $Log:    dd.c,v $
  1334. +  * Revision 1.2  86/08/07  15:55:17  root
  1335. +  * Added remote mag tape capability. ADR.
  1336. +  * 
  1337.    * Revision 1.1  86/08/07  15:52:39  root
  1338.    * Initial revision
  1339.    * 
  1340. ***************
  1341. *** 15,20 ****
  1342. --- 18,24 ----
  1343.   
  1344.   #include <stdio.h>
  1345.   #include <signal.h>
  1346. + #include <rmt.h>    /* remote mag tape library */
  1347.   
  1348.   #define    BIG    2147483647
  1349.   #define    LCASE    01
  1350. SHAR_EOF
  1351. fi # end of overwriting check
  1352. echo shar: extracting "'tar.1.patch'" '(2168 characters)'
  1353. if test -f 'tar.1.patch'
  1354. then
  1355.     echo shar: will not over-write existing file "'tar.1.patch'"
  1356. else
  1357. cat << \SHAR_EOF > 'tar.1.patch'
  1358. RCS file: RCS/tar.1,v
  1359. retrieving revision 1.1
  1360. diff -c -r1.1 tar.1
  1361. *** /tmp/,RCSt1012257    Thu Oct  9 16:51:06 1986
  1362. --- tar.1    Thu Oct  9 16:50:23 1986
  1363. ***************
  1364. *** 1,7 ****
  1365.   ...
  1366. ! ... $Header: tar.1,v 1.1 86/08/07 16:02:56 root Exp $
  1367.   ... 
  1368.   ... $Log:    tar.1,v $
  1369.   ... Revision 1.1  86/08/07  16:02:56  root
  1370.   ... Initial revision
  1371.   ... 
  1372. --- 1,13 ----
  1373.   ...
  1374. ! ... $Header: tar.1,v 1.3 86/10/09 16:50:19 root Locked $
  1375.   ... 
  1376.   ... $Log:    tar.1,v $
  1377. + ... Revision 1.3  86/10/09  16:50:19  root
  1378. + ... Changed to indicate use of 4.3 rcp syntax. ADR.
  1379. + ... 
  1380. + ... Revision 1.2  86/08/07  16:05:34  root
  1381. + ... Added doc of remote mag tape facility. ADR.
  1382. + ... 
  1383.   ... Revision 1.1  86/08/07  16:02:56  root
  1384.   ... Initial revision
  1385.   ... 
  1386. ***************
  1387. *** 106,112 ****
  1388.   .B f
  1389.   .I Tar
  1390.   uses the next argument as the name of the archive instead of
  1391. ! /dev/rmt?. If the name of the file is `\-', tar writes to standard output or
  1392.   reads from standard input, whichever is appropriate. Thus,
  1393.   .I tar
  1394.   can be used as the head or tail of a filter chain.
  1395. --- 112,142 ----
  1396.   .B f
  1397.   .I Tar
  1398.   uses the next argument as the name of the archive instead of
  1399. ! /dev/rmt?.
  1400. ! .sp
  1401. ! If the file name has either of the forms
  1402. ! .RI [ user @] system :/dev/???,
  1403. ! or
  1404. ! .IR system [. user ]:/dev/???,
  1405. ! .I tar
  1406. ! will use the tape drive /dev/??? on the remote system
  1407. ! .IR system ,
  1408. ! via
  1409. ! .IR rsh (1),
  1410. ! and
  1411. ! .IR rmt (8).
  1412. ! The optional
  1413. ! .I user
  1414. ! portion of the pathname specifies the login name to use on the
  1415. ! remote system.
  1416. ! If it is not supplied, the current user's login name will be used.
  1417. ! In all the cases, the user must have the appropriate
  1418. ! permissions on the remote machine, in order to use this facility.
  1419. ! (The first form is the 4.3BSD syntax for
  1420. ! .IR rcp (1),
  1421. ! the second is from 4.2BSD.)
  1422. ! .sp
  1423. ! If the name of the file is `\-', tar writes to standard output or
  1424.   reads from standard input, whichever is appropriate. Thus,
  1425.   .I tar
  1426.   can be used as the head or tail of a filter chain.
  1427. ***************
  1428. *** 199,201 ****
  1429. --- 229,233 ----
  1430.   or
  1431.   .B u
  1432.   options, directory modification times may not be set correctly.
  1433. + .br
  1434. + Using a remote system's tape drive can be slow.
  1435. SHAR_EOF
  1436. fi # end of overwriting check
  1437. echo shar: extracting "'tar.c.patch'" '(911 characters)'
  1438. if test -f 'tar.c.patch'
  1439. then
  1440.     echo shar: will not over-write existing file "'tar.c.patch'"
  1441. else
  1442. cat << \SHAR_EOF > 'tar.c.patch'
  1443. RCS file: RCS/tar.c,v
  1444. retrieving revision 1.1
  1445. diff -c -r1.1 tar.c
  1446. *** /tmp/,RCSt1011918    Thu Oct  9 16:44:38 1986
  1447. --- tar.c    Thu Aug  7 16:00:55 1986
  1448. ***************
  1449. *** 1,9 ****
  1450.   #ifndef lint
  1451. ! static char *RCSid = "$Header: tar.c,v 1.1 86/08/07 15:52:50 root Exp $";
  1452.   #endif
  1453.   
  1454.   /*
  1455.    * $Log:    tar.c,v $
  1456.    * Revision 1.1  86/08/07  15:52:50  root
  1457.    * Initial revision
  1458.    * 
  1459. --- 1,12 ----
  1460.   #ifndef lint
  1461. ! static char *RCSid = "$Header: tar.c,v 1.2 86/08/07 16:00:34 root Locked $";
  1462.   #endif
  1463.   
  1464.   /*
  1465.    * $Log:    tar.c,v $
  1466. +  * Revision 1.2  86/08/07  16:00:34  root
  1467. +  * Added remote mag tape capability. ADR.
  1468. +  * 
  1469.    * Revision 1.1  86/08/07  15:52:50  root
  1470.    * Initial revision
  1471.    * 
  1472. ***************
  1473. *** 29,34 ****
  1474. --- 32,38 ----
  1475.    * Tape Archival Program
  1476.    */
  1477.   #include <stdio.h>
  1478. + #include <rmt.h>    /* remote mag tape library */
  1479.   #include <sys/param.h>
  1480.   #include <sys/stat.h>
  1481.   #include <sys/dir.h>
  1482. SHAR_EOF
  1483. fi # end of overwriting check
  1484. #    End of shell archive
  1485. exit 0
  1486.  
  1487.